package com.xcm.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xcm.annotation.Operate;
import com.xcm.constant.BaseConstant;
import com.xcm.constant.SysAuthorityConstants;
import com.xcm.dao.RoleAuthorityMapper;
import com.xcm.dao.SysAuthorityMapper;
import com.xcm.exception.ServiceException;
import com.xcm.model.RoleAuthority;
import com.xcm.model.SysAuthority;
import com.xcm.model.SysUser;
import com.xcm.model.vo.SysAuthorityTreeVo;
import com.xcm.model.vo.SysAuthorityVo;
import com.xcm.page.PageInfo;
import com.xcm.service.SysAuthorityService;
import com.xcm.util.SessionUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static org.apache.commons.beanutils.BeanUtils.copyProperties;

/**
 * 权限服务实现
 *
 * @author 林强
 * @date 2018-04-12 11:15
 */
@Service(value = "sysAuthorityService")
public class SysAuthorityServiceImpl implements SysAuthorityService {
    private static Logger logger = LoggerFactory.getLogger(SysAuthorityServiceImpl.class);
    @Autowired
    private SysAuthorityMapper sysAuthorityMapper;
    @Autowired
    private RoleAuthorityMapper roleAuthorityMapper;
    @Autowired
    private HttpServletRequest request;

    /**
     * 新增
     *
     * @param sysAuthority
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("新增权限")
    @Override
    public int save(SysAuthority sysAuthority) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysAuthority.setAble(SysAuthorityConstants.ABLE_USE);
        sysAuthority.setStatus(SysAuthorityConstants.STATUS_USE);
        sysAuthority.setCreateTime(System.currentTimeMillis());
        sysAuthority.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysAuthority.setCreateUserId(currentUser.getUserId());
        }
        return sysAuthorityMapper.save(sysAuthority);
    }

    /**
     * @param sysAuthority 新增的权限
     * @return
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("新增权限并返回id")
    @Override
    public SysAuthority saveAndGetId(SysAuthority sysAuthority) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysAuthority.setAble(SysAuthorityConstants.ABLE_USE);
        sysAuthority.setStatus(SysAuthorityConstants.STATUS_USE);
        sysAuthority.setCreateTime(System.currentTimeMillis());
        sysAuthority.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysAuthority.setCreateUserId(currentUser.getUserId());
        }
        int effectRow = sysAuthorityMapper.saveAndGetId(sysAuthority);
        if (effectRow > 0) {
            List<RoleAuthority> roleAuthorityList = new ArrayList<>();
            //新增成功后添加到系统超级管理员角色
            RoleAuthority roleAuthority = new RoleAuthority();
            roleAuthority.setAuthorityId(sysAuthority.getAuthorityId());
            roleAuthority.setRoleId(BaseConstant.SUPER_ADMIN_ROLE_ID);
            roleAuthorityList.add(roleAuthority);
            roleAuthorityMapper.batchSave(roleAuthorityList);
        }
        return effectRow > 0 ? sysAuthority : null;
    }

    /**
     * 根据id刪除(级联删除子类)
     *
     * @param id 删除的数据的id
     * @return 1成功，0失败，-1有关联不能删除
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("删除权限(级联删除子类)")
    @Override
    public int deleteById(Integer id) throws ServiceException {
        SysAuthority sysAuthority = sysAuthorityMapper.getById(id);
        if (null == sysAuthority) {
            throw new ServiceException(SysAuthorityConstants.NOT_EXITS);
        }
        //系统权限不能删除
        if (null == sysAuthority.getParentId()
                && SysAuthorityConstants.SYS_AUTHORITY_TYPE_SYSTEM.equals(sysAuthority.getType())) {
            throw new ServiceException(SysAuthorityConstants.DELETE_FAIL_CONTAINS_CAN_NOT_DELETE);
        }
        //有关联关系不能删除
        int roleAuthority = roleAuthorityMapper.countRoleAuthority(id, null);
        if (roleAuthority > 0) {
            //与角色有关联
            throw new ServiceException(SysAuthorityConstants.DELETE_FAIL_HAS_RELATION_WITH_ROLE);
        }
        SysAuthority sysAuthorityParam = new SysAuthority();
        sysAuthorityParam.setParentId(id);
        int countByParentId = sysAuthorityMapper.countByParam(sysAuthorityParam);
        if (countByParentId > 0) {
            //有子类
            throw new ServiceException(SysAuthorityConstants.DELETE_FAIL_HAS_RELATION);
        }
        return sysAuthorityMapper.deleteById(id);
    }

    /**
     * 根据id批量删除
     *
     * @param authorityIdArr 权限id(多个以英文逗号隔开)
     * @return
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("批量删除权限(级联删除子类)")
    @Override
    public int batchDelete(String authorityIdArr) throws ServiceException {
        String[] idArr = StringUtils.split(authorityIdArr, BaseConstant.COMMA_ZH);
        if (ArrayUtils.isEmpty(idArr)) {
            return 0;
        }
        int row = 0;
        for (String anIdArr : idArr) {
            if (StringUtils.isNotBlank(anIdArr)) {
                int deleteRow = deleteById(Integer.parseInt(anIdArr));
                if (-1 == deleteRow) {
                    throw new ServiceException(SysAuthorityConstants.DELETE_FAIL_CAN_NOT_DELETE);
                }
                row += deleteRow;
            }
        }
        return row;
    }

    /**
     * 查询系统权限集合
     *
     * @return
     */
    @Override
    public List<SysAuthority> listSystem() {
        return sysAuthorityMapper.listSystem();
    }

    /**
     * 递归获取某个权限id下面的所有子单位(包括自己)
     */
    @Override
    public void findAllSysAuthorityByParent(Set<SysAuthority> sysAuthoritySet, Integer pid) {
        SysAuthority parent = sysAuthorityMapper.getById(pid);
        List<SysAuthority> sysAuthorityList = new ArrayList<>();
        if (null != parent) {
            sysAuthorityList.add(parent);
            sysAuthoritySet.addAll(new ArrayList<>(sysAuthorityList));
            Map<String, Object> paramMap = new HashMap<>(1);
            paramMap.put("parentId", pid);
            List<SysAuthority> children = sysAuthorityMapper.list(paramMap);
            if (CollectionUtils.isNotEmpty(children)) {
                for (SysAuthority child : children) {
                    //递归子权限
                    findAllSysAuthorityByParent(sysAuthoritySet, child.getAuthorityId());
                }
            }
        }
    }

    /**
     * 更新
     *
     * @param sysAuthority 更新的权限
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("修改权限")
    @Override
    public int update(SysAuthority sysAuthority) throws ServiceException {
        //系统不能修改sign
        if (SysAuthorityConstants.SYS_AUTHORITY_TYPE_SYSTEM.equals(sysAuthority.getType())) {
            SysAuthority sysAuthorityOld = sysAuthorityMapper.getById(sysAuthority.getAuthorityId());
            if (null == sysAuthorityOld) {
                throw new ServiceException(SysAuthorityConstants.NOT_EXITS);
            }
            if (!sysAuthorityOld.getSign().equals(sysAuthority.getSign())) {
                throw new ServiceException(SysAuthorityConstants.UPDATE_FAIL_CANNOT_UPDATE_SIGN);
            }
        }
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysAuthority.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysAuthority.setUpdateUserId(currentUser.getUserId());
        }
        return sysAuthorityMapper.update(sysAuthority);
    }

    /**
     * 根据id查询
     *
     * @param id 主键
     * @return
     */
    @Override
    public SysAuthority getById(Integer id) {
        return sysAuthorityMapper.getById(id);
    }

    /**
     * 查询集合
     *
     * @param paramMap 参数map
     * @return
     */
    @Override
    public List<SysAuthority> list(Map<String, Object> paramMap) {
        return sysAuthorityMapper.list(paramMap);
    }

    /**
     * 根据角色ID查询角色树状集合(已有的权限默认选中)
     *
     * @param roleId 角色id
     * @return
     */
    @Override
    public List<SysAuthorityTreeVo> listTree(Integer roleId) {
        return sysAuthorityMapper.listTree(roleId);
    }

    /**
     * 列表分页
     *
     * @param paramMap 参数map
     * @param pageNum  第几页
     * @param pageSize 每页几条
     * @return
     */
    @Override
    public PageInfo listPage(Map<String, Object> paramMap, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<SysAuthority> page = sysAuthorityMapper.listPage(paramMap);
        return PageInfo.build(page);
    }

    /**
     * 判断权限是否可添加
     *
     * @param sysAuthority 需要判断是否存在的权限
     * @return
     */
    @Override
    public String canSave(SysAuthority sysAuthority) {
        //验证是否存在
        if (sysAuthority.getType().equals(SysAuthorityConstants.SYS_AUTHORITY_TYPE_SYSTEM)) {
            //系统权限名称必须唯一
            SysAuthority sysAuthority1 = new SysAuthority();
            sysAuthority1.setAuthorityName(sysAuthority.getAuthorityName());
            int isSystemNameOk = sysAuthorityMapper.countByParam(sysAuthority1);
            if (isSystemNameOk > 0) {
                return SysAuthorityConstants.AUTHORITY_EXITS;
            }
            sysAuthority1.setAuthorityName(null);
            sysAuthority1.setSign(sysAuthority.getSign());
            int isSignOk = sysAuthorityMapper.countByParam(sysAuthority1);
            if (isSignOk > 0) {
                return SysAuthorityConstants.AUTHORITY_SIGN_EXITS;
            }
        } else if (null != sysAuthority.getParentId()) {
            //某父级下的子权限名称不能重复
            SysAuthority check = new SysAuthority();
            check.setAuthorityName(sysAuthority.getAuthorityName());
            check.setParentId(sysAuthority.getParentId());
            int isSignOk = sysAuthorityMapper.countByParam(check);
            if (isSignOk > 0) {
                return SysAuthorityConstants.AUTHORITY_EXITS;
            }
            return "";
        }
        return sysAuthorityMapper.countByParam(sysAuthority) > 0 ? SysAuthorityConstants.AUTHORITY_EXITS : "";
    }

    /**
     * 判断是否可删除
     *
     * @param authorityId 需要删除的权限id
     * @return 可删除返回true, 反之false
     */
    @Override
    public boolean canDelete(Integer authorityId) {
        SysAuthority sysAuthority = sysAuthorityMapper.getById(authorityId);
        if (null == sysAuthority) {
            return true;
        }
        //系统权限不能删除
        if (null == sysAuthority.getParentId()
                && SysAuthorityConstants.SYS_AUTHORITY_TYPE_SYSTEM.equals(sysAuthority.getType())) {
            return false;
        }
        //有关联关系不能删除
        int roleAuthority = roleAuthorityMapper.countRoleAuthority(authorityId, null);
        if (roleAuthority > 0) {
            return false;
        }
        //检查是否有子类
        SysAuthority sysAuthorityParam = new SysAuthority();
        sysAuthorityParam.setParentId(authorityId);
        int countByParentId = sysAuthorityMapper.countByParam(sysAuthorityParam);
        return countByParentId <= 0;
    }

    /**
     * 根据用户系统查询用户的所有权限
     *
     * @param userId 用户id
     * @return JSONObject
     */
    @Override
    public JSONObject getAuthorityByUser(Integer userId) {
        JSONObject resultMap = new JSONObject();
        try {
            //用户有用的系统权限
            List<SysAuthority> systemAuthorityList = sysAuthorityMapper.getSystemListByUser(userId);
            for (SysAuthority systemAuthority : systemAuthorityList) {
                JSONObject system = new JSONObject();
                if (null == systemAuthority) {
                    continue;
                }
                if (StringUtils.isBlank(systemAuthority.getSign())) {
                    continue;
                }
                //查询用户在该系统下的所有权限
                //List<SysAuthority> sysAuthorityList = new ArrayList<>();
                //findUserAuthByParent(sysAuthorityList, systemAuthority, userId);
                List<SysAuthority> sysAuthorityList = sysAuthorityMapper.findAllAuthorityByParentIdAndUserId(systemAuthority.getAuthorityId(), userId);
                JSONArray sysAuthorityListJson = toJSONOArrayFromList(sysAuthorityList);
                //权限转换成vo类并设置成tree结构
                List<SysAuthorityVo> sysAuthorityVoList = parseToVoAndSetParent(sysAuthorityList);
                //找到系统下的所有菜单
                JSONArray menusJson = new JSONArray();
                for (SysAuthorityVo child : sysAuthorityVoList) {
                    if (null != child.getParentId() && child.getParentId().equals(systemAuthority.getAuthorityId())) {
                        //菜单
                        if (StringUtils.isNotBlank(child.getType())
                                && child.getType().equals(SysAuthorityConstants.SYS_AUTHORITY_TYPE_MENU)) {
                            JSONObject childJson = toJSONObject(child);
                            menusJson.add(childJson);
                        }
                    }
                }
                system.put("menus", menusJson);
                system.put("allAuth", sysAuthorityListJson);
                resultMap.put(systemAuthority.getSign(), system);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return resultMap;
        }
        return resultMap;
    }

    /**
     * 权限VO类转json对象
     *
     * @param sysAuthorityVo 权限对象
     * @return
     */
    private JSONObject toJSONObject(SysAuthorityVo sysAuthorityVo) {
        JSONObject jsonObject = new JSONObject();
        if (null == sysAuthorityVo) {
            return null;
        }
        jsonObject.put("authorityId", sysAuthorityVo.getAuthorityId());
        jsonObject.put("parentId", sysAuthorityVo.getParentId());
        jsonObject.put("type", sysAuthorityVo.getType());
        jsonObject.put("authorityName", sysAuthorityVo.getAuthorityName());
        jsonObject.put("label", sysAuthorityVo.getAuthorityName());
        jsonObject.put("sign", sysAuthorityVo.getSign());
        jsonObject.put("url", sysAuthorityVo.getUrl());
        jsonObject.put("classes", sysAuthorityVo.getClasses());
        jsonObject.put("itemId", sysAuthorityVo.getItemId());
        jsonObject.put("icon", sysAuthorityVo.getIcon());
        jsonObject.put("sortNum", sysAuthorityVo.getSortNum());
        if (CollectionUtils.isNotEmpty(sysAuthorityVo.getChildren())) {
            JSONArray children = new JSONArray();
            for (int i = 0; i < sysAuthorityVo.getChildren().size(); i++) {
                JSONObject child = toJSONObject(sysAuthorityVo.getChildren().get(i));
                children.add(child);
            }
            jsonObject.put("children", children);
        } else {
            jsonObject.put("children", new JSONArray());
        }
        return jsonObject;
    }

    /**
     * 权限VO类转json对象集合
     *
     * @param sysAuthorityList 权限对象集合
     * @return
     */
    private JSONArray toJSONOArrayFromList(List<SysAuthority> sysAuthorityList) {
        if (null == sysAuthorityList || sysAuthorityList.isEmpty()) {
            return null;
        }
        JSONArray jsonArray = new JSONArray();
        for (int i = 0; i < sysAuthorityList.size(); i++) {
            SysAuthority sysAuthority = sysAuthorityList.get(i);
            JSONObject jsonObject = new JSONObject();
            if (null == sysAuthority) {
                return null;
            }
            jsonObject.put("authorityId", sysAuthority.getAuthorityId());
            jsonObject.put("parentId", sysAuthority.getParentId());
            jsonObject.put("type", sysAuthority.getType());
            jsonObject.put("authorityName", sysAuthority.getAuthorityName());
            jsonObject.put("sign", sysAuthority.getSign());
            jsonObject.put("url", sysAuthority.getUrl());
            jsonObject.put("classes", sysAuthority.getClasses());
            jsonObject.put("itemId", sysAuthority.getItemId());
            jsonObject.put("icon", sysAuthority.getIcon());
            jsonObject.put("sortNum", sysAuthority.getSortNum());
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }


    /**
     * 获取集合中对象的id
     *
     * @param sysAuthoritySet
     * @return
     */
    private Set<Integer> getIdFromListAuthority(Set<SysAuthority> sysAuthoritySet) {
        Set<Integer> idSet = new HashSet<>();
        if (CollectionUtils.isEmpty(sysAuthoritySet)) {
            return idSet;
        }
        for (SysAuthority sysAuthority : sysAuthoritySet) {
            idSet.add(sysAuthority.getAuthorityId());
        }
        return idSet;
    }

    /**
     * 递归查询用户在某系统下的所有权限
     *
     * @param sysAuthorityList
     * @param systemAuthority
     * @param userId
     */
    private void findUserAuthByParent(List<SysAuthority> sysAuthorityList, SysAuthority systemAuthority, Integer userId) {
        List<SysAuthority> sysAuthorityListNew = new ArrayList<>();
        if (null != systemAuthority) {
            sysAuthorityListNew.add(systemAuthority);
            sysAuthorityList.addAll(new ArrayList<>(sysAuthorityListNew));
            List<SysAuthority> children = sysAuthorityMapper.getAuthorityByUserId(userId, systemAuthority.getAuthorityId());
            if (CollectionUtils.isNotEmpty(children)) {
                for (SysAuthority child : children) {
                    //递归子权限
                    findUserAuthByParent(sysAuthorityList, child, userId);
                }
            }
        }
    }

    /**
     * 权限转换成vo类并设置成tree结构
     *
     * @param sysAuthorityList
     * @return
     */
    private List<SysAuthorityVo> parseToVoAndSetParent(List<SysAuthority> sysAuthorityList) {
        //转成VO类
        List<SysAuthorityVo> userAuthorityVoList = new ArrayList<>();
        try {
            for (SysAuthority aSysAuthorityList : sysAuthorityList) {
                SysAuthorityVo vo = new SysAuthorityVo();
                copyProperties(vo, aSysAuthorityList);
                userAuthorityVoList.add(vo);
            }
            // 循环list，找到自己的"父亲"，并加入到"父亲"的getListchild中
            for (SysAuthorityVo sun : userAuthorityVoList) {
                if (sun.getParentId() == null || sun.getParentId() == 0) {
                    continue;
                }
                for (SysAuthorityVo parent : userAuthorityVoList) {
                    if (parent.getAuthorityId().equals(sun.getParentId())) {
                        if (parent.getChildren() == null) {
                            List<SysAuthorityVo> children = new ArrayList<>();
                            children.add(sun);
                            parent.setChildren(children);
                        } else {
                            if (!parent.getChildren().contains(sun)) {
                                parent.getChildren().add(sun);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("SysAuthorityServiceImpl parseToVoAndSetParent 权限转换成vo类并设置成tree结构异常：" + e.getMessage());
        }
        return userAuthorityVoList;
    }

    /**
     * 找到权限所属系统
     *
     * @param child
     * @return
     */
    public SysAuthority findSystem(SysAuthority child) {
        if (null == child) {
            return null;
        }
        if (null != child.getParentId()) {
            SysAuthority parent = sysAuthorityMapper.getById(child.getParentId());
            if (parent == null) {
                return null;
            }
            if (parent.getParentId() != null) {
                return findSystem(parent);
            }
            return parent;
        }
        return child;
    }
}
